'''
图片转化为可注释的字符
'''

import os
import threading
import tkinter as tk
from tkinter import END
from tkinter import filedialog

from PIL import Image

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
coefficient = 1  # 缩放系数 1为无缩放，2为缩小2倍


def thread_it(func, *args):
    """将函数打包进线程"""
    # 创建
    t = threading.Thread(target=func, args=args)
    # 守护 !!!
    t.setDaemon(True)
    # 启动
    t.start()
    # 阻塞--卡死界面！
    # t.join()



class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title("DDPl图片转字符串画")
        self.root.configure(bg='#2c3038')
        self.root.option_add('*Font', '楷体')
        # self.root.geometry("500x200+1100+150")
        # 程序运行时在屏幕中间打开
        sw = self.root.winfo_screenwidth()
        sh = self.root.winfo_screenheight()
        ww = 1055
        wh = 580
        x = (sw - ww) / 2
        y = (sh - wh) / 3
        self.root.geometry("%dx%d+%d+%d" % (ww, wh, x, y))
        self.root.resizable(False, False)
        self.root.update()
        self.root.wm_attributes('-topmost', 1)
        self.interface()

    def interface(self):
        self.w1 = tk.Entry(self.root, textvariable='请输入目标路径', bg='#25272c', fg='#b2b2b2')
        self.w1.grid(row=0, column=0, columnspan=3, ipadx=210, ipady=8, padx=10, pady=10)
        self.Button1 = tk.Button(self.root, text="选择目标文件", command=lambda: thread_it(self.event_选择目标文件), width=10,
                                 bg='#4780ac', fg='#d9f5ff', activebackground='#4d535f', activeforeground='#fdfdfd')
        self.Button1.grid(row=0, column=3, ipadx=20, ipady=10, padx=5, pady=10)
        self.Button2 = tk.Button(self.root, text="转换字符图片", command=lambda: thread_it(self.event_转换字符图片), width=10,
                                 bg='#4a8e53', fg='#d9f5ff', activebackground='#4d535f', activeforeground='#fdfdfd')
        self.Button2.grid(row=0, column=4, ipadx=20, ipady=10, padx=5, pady=10)
        self.Button3 = tk.Button(self.root, text="清空输出信息", command=lambda: thread_it(self.event_清空输出信息), width=10,
                                 bg='#2c3038', fg='#d9f5ff', activebackground='#4d535f', activeforeground='#fdfdfd')
        self.Button3.grid(row=0, column=5, ipadx=20, ipady=10, padx=5, pady=10)
        self.text = tk.Text(self.root, bg='#25272c', fg='#777c8a')
        self.text.grid(row=1, column=0, columnspan=6, ipadx=195, ipady=50, padx=10, pady=10)
        # 新建滚动条
        self.scroll = tk.Scrollbar()
        # 两个控件关联
        self.scroll.config(command=self.text.yview)
        self.text.config(yscrollcommand=self.scroll.set)

    def event_选择目标文件(self):
        path_ = filedialog.askopenfilename(filetypes=[("图片", [".jpg", ".png", ".jpeg"])])
        if path_ == "":
            self.w1.get()
        else:
            path_ = path_.replace("/", "\\")  # 实际在代码中执行的路径为“\“ 所以替换一下
            print(path_)
            self.w1.delete(0, END)
            self.w1.insert(0, path_)

    def event_转换字符图片(self):
        try:
            data_path = self.w1.get()
            if data_path is not None:
                self.convert_pictures(data_path)
        except Exception as e:
            self.text.insert(tk.INSERT, "   " + str(e) + '\n')
            self.text.see(END)
            print(e)

    def event_清空输出信息(self):
        try:
            self.text.delete('1.0', END)
        except Exception as e:
            print(e)
            pass

    def convert_pictures(self, img):
        # 打开并调整图片的宽和高
        im = Image.open(img)
        WIDTH = im.size[0]
        HEIGHT = im.size[1]
        im = im.resize((WIDTH, HEIGHT), Image.NEAREST)
        txt = ""
        for i in range(0, HEIGHT, coefficient):
            for j in range(0, WIDTH, coefficient):
                # 将(j, i)坐标的 RGB 像素转为字符后添加到txt字符串
                txt += self.get_char(*im.getpixel((j, i)))
                txt += '  '
            # 遍历完一行后需要增加换行符
            txt += '\n'
        self.text.insert(tk.INSERT, txt)
        self.text.see(END)
        print(txt)
        # 获取文件目录
        de_path = os.path.dirname(img)
        # 获取文件名
        de_name = os.path.basename(img)
        with open(de_path + "//" + de_name + ".txt", 'a+') as f:
            f.write(txt)
        self.text.insert(tk.INSERT, "已在图片文件夹下生成字符图txt..." + '\n')
        self.text.see(END)

    def get_char(self, r, g, b, alpha=256):
        if alpha == 0:
            return ' '
        length = len(ascii_char)
        # 将RGB值转为灰度值 gray，灰度值范围为0-255
        gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
        # 灰度值范围为0-255, 而字符集只有 70
        # 需要进行如下处理才能将灰度值映射到指定的字符上
        unit = (256.0 + 1) / length
        # 返回灰度值对应的字符
        return ascii_char[int(gray / unit)]


if __name__ == "__main__":
    a = GUI()
    a.root.mainloop()


